home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Ham⁄GPS / SoftKiss.src.1.8 Folder / SoftKiss.src.1.8 / core / sfk_core_soft_tnc.c < prev    next >
Text File  |  1993-03-17  |  9KB  |  395 lines

  1. /*
  2.  * SoftKiss - software emulation of a tnc in tnc mode
  3.  * by Aaron Wohl / N3LIW (aw0g+@andrew.cmu.edu) jul 1992
  4.  * 6393 Penn Ave #303
  5.  * Pittsburgh PA, 15206
  6.  * work: (412)-268-5032
  7.  * home: (412)-731-6159
  8.  */
  9.  
  10. #include "sfk_core.h"
  11. #include "sfk_core_private.h"
  12. #include "driver_shell.h"
  13. #include <Serial.h>
  14.  
  15. #define STNC_put(xx_p,xx_str) \
  16.     sfk_cu_write(&p->K_IN.io_buf,(xx_str),strlen(xx_str))
  17.  
  18. /*
  19.  * return an estimate of the number of bytes to read
  20.  */
  21. static long soft_tnc_bytes_available(sfk_prt_pt p)
  22. {
  23.     return sfk_cu_read_size(&p->K_IN.io_buf);
  24. }
  25.  
  26. /*
  27.  * read some data from packets into the serial input buffer
  28.  */
  29. static int soft_tnc_bytes_read(sfk_prt_pt p,int is_async)
  30. {
  31.     register IOParam *ipb= p->K_IN.kp_pb;
  32.     if(ipb==0)
  33.         return 1;    //no serial buffer to read into
  34.     ipb->ioActCount=0;  //read zero so far ???
  35.     ipb->ioActCount+=sfk_cu_read(
  36.         &p->K_IN.io_buf,
  37.         ipb->ioBuffer+ipb->ioActCount,
  38.         ipb->ioReqCount-ipb->ioActCount);
  39.  
  40. /*
  41.  * done for one of two reasons, no more data to send
  42.  * or no more room to put it.  In eithor case
  43.  * let the pending read request finish
  44.  * since something was read
  45.  */
  46. done:
  47.     if(is_async)
  48.         sfk_mark_read_done(p,0);    //read all we need to
  49.     else {
  50.         p->K_IN.kp_pb->ioResult=0;
  51.         p->K_IN.kp_pb=0;
  52.     }
  53.     return 0;
  54. }
  55.  
  56. /*
  57.  * echo a character up arrowifiying control chars
  58.  */
  59. static void soft_tnc_echo_quoted_ch(sfk_prt_pt p,char ch)
  60. {
  61.     if(ch=='\t')ch=' ';
  62.     if(ch<' ') {
  63.         sfk_cu_write(&p->K_IN.io_buf,"^",1);
  64.         ch+='@';
  65.         sfk_cu_write(&p->K_IN.io_buf,&ch,1);
  66.     } else
  67.         sfk_cu_write(&p->K_IN.io_buf,&ch,1);
  68. }
  69.  
  70. /*
  71.  * print a command prompt and echo line buffer text
  72.  */
  73. static void soft_tnc_prompt(sfk_prt_pt p)
  74. {
  75.     long len=p->cmd_buf_len;
  76.     char *s=p->cmd_buf;
  77.     p->cmd_did_prompt=TRUE;
  78.     STNC_put(p,sfk_PN(p->cmd_port)->port_name);
  79.     STNC_put(p,SFK_TEXT(53));
  80.     while(--len>=0)        //echo command line so far
  81.       soft_tnc_echo_quoted_ch(p,*s++);
  82. }
  83.  
  84. #define CTL(xx_ch) ((xx_ch)-'@')
  85.  
  86. /*
  87.  * check last character that caused read_line to wake up
  88.  * return FALSE if a compleate line has been read
  89.  */
  90. static int soft_tnc_read_action(sfk_prt_pt p)
  91. {
  92.     char ch= *(p->cmd_buf+(p->cmd_buf_len-1));
  93.     ch&=0x7f;
  94.     switch(ch) {
  95.       case 0x7f:
  96.       case CTL('H'):
  97.           p->cmd_buf_len--;
  98.           if(p->cmd_buf_len==0)break; //^H at start of line
  99.           soft_tnc_echo_quoted_ch(p,ch);
  100.           p->cmd_buf_len--;
  101.           ch= *(p->cmd_buf+p->cmd_buf_len);
  102.           if(ch<' ') //erase a control character by spacing over it???
  103.               STNC_put(p,"\010\010  \010\010");
  104.           else
  105.               STNC_put(p,"\010 \010");
  106.           break;
  107.       case CTL('U'):
  108.       case CTL('C'):
  109.           p->cmd_buf_len=1;
  110.       case CTL('R'): // fall into
  111.           soft_tnc_echo_quoted_ch(p,ch);
  112.           p->cmd_did_prompt=FALSE;
  113.           STNC_put(p,SFK_TEXT(59));
  114.           p->cmd_buf_len--;
  115.           break;
  116.       case CTL('J'):
  117.       case CTL('M'):
  118.           p->cmd_buf_len--;
  119.           return FALSE;
  120.           break;
  121.       default:
  122.           soft_tnc_echo_quoted_ch(p,ch);
  123.     }  
  124.     return TRUE;
  125. }
  126.  
  127. /*
  128.  * print a c string converting \n to \n\r for terminal output
  129.  */
  130. static void soft_tnc_print_c_string(sfk_prt_pt p,char *s)
  131. {
  132.   char *tail;
  133.   long slen;
  134.   if((*s)==0)
  135.       return;
  136.   while((tail=strchr(s,'\n'))!=0) {
  137.     sfk_cu_write(&p->K_IN.io_buf,s,(tail-s)+1);
  138.     s=tail+1;
  139.     STNC_put(p,SFK_TEXT(60));
  140.   }
  141.   slen=strlen(s);
  142.   sfk_cu_write(&p->K_IN.io_buf,s,slen);
  143.   if(slen>1)
  144.     STNC_put(p,SFK_TEXT(59));     //force end of line
  145. }
  146.  
  147. /*
  148.  * execute the passed command
  149.  */
  150. static void soft_tnc_execute_cmd(sfk_prt_pt p,char *execute_me)
  151. {
  152.     sfk_io_record cmd;
  153.     char out_buf[4000];
  154.     sfk_INIT_CPB(cmd,-1000,sfk_CMD_msg);
  155.     out_buf[0]=0;
  156.     sfk_parse_from(&cmd,execute_me,strlen(execute_me),out_buf,sizeof(out_buf),p->cmd_port);
  157.     sfk_control(&cmd);
  158.     p->cmd_port=cmd.do_this.cknd.sfk_msg.portno;
  159.     if(out_buf[0]!=0)
  160.       soft_tnc_print_c_string(p,out_buf);
  161. }
  162.  
  163. /*
  164.  * process command lines in tnc mode
  165.  */
  166. static void soft_tnc_cmd(sfk_prt_pt p)
  167. {
  168.     long read_len;
  169.     if(p->sfk_IVAR(kiss))
  170.         return;        /*no command lines in kiss mode*/
  171.     if(!p->cmd_did_prompt)
  172.         soft_tnc_prompt(p);
  173.     read_len=sfk_cu_read_line(&p->K_OUT.io_buf,
  174.         p->cmd_buf+p->cmd_buf_len,
  175.         p->cmd_buf_limit-p->cmd_buf_len);
  176.     if(read_len==0)
  177.         return;
  178.     //all but the last character are safe to do as a chunk
  179.     sfk_cu_write(&p->K_IN.io_buf,p->cmd_buf+p->cmd_buf_len,sfk_imax(0,read_len-1));
  180.     p->cmd_buf_len+=read_len;
  181.     if(soft_tnc_read_action(p))    //handle character tha caused end of line
  182.         return;                    //don't have a full line yet
  183.     *(p->cmd_buf+p->cmd_buf_len)=0;
  184.     p->cmd_did_prompt=FALSE;
  185.     STNC_put(p,SFK_TEXT(59));
  186.     p->cmd_buf_len=0;
  187.     soft_tnc_execute_cmd(p,p->cmd_buf);
  188. }
  189.  
  190. /*
  191.  * called periodicly
  192.  */
  193. static void soft_tnc_tick(sfk_prt_pt p)
  194. {
  195.     soft_tnc_bytes_read(p,TRUE);
  196.     soft_tnc_cmd(p);
  197.     soft_tnc_bytes_read(p,TRUE);
  198. }
  199.  
  200. /*
  201.  * fake driver for serial input in tnc mode
  202.  */
  203. static short soft_tnc_in(CntrlParam *pb,DCtlPtr de,short op,void *extra)
  204. {
  205.     short csCode=pb->csCode;
  206.     register IOParam *ipb= (IOParam *)pb;
  207.     sfk_prt_pt p=extra;
  208.     switch(op) {
  209.     case sh_OPEN:
  210.         if(sfk_open_me(de))
  211.             return ioErr;
  212.         break;
  213.     case sh_CLOSE:
  214.         sfk_close_me(de);
  215.         break;
  216.     case sh_STATUS:
  217.         if(csCode==2) { //SetGetBuf
  218.             long *iocnt= (long*)&pb->csParam;
  219.             *iocnt=soft_tnc_bytes_available(p);
  220.         } else if(csCode==8) { //SetStatus
  221.             SerStaRec st;
  222.             memset(&st,0,sizeof(st));
  223.             st.rdPend= (soft_tnc_bytes_available(p)>0);
  224.             memcpy(&pb->csParam,&st,5);    //6? instead of 5?
  225.         }
  226.         break;
  227.     case sh_PRIME:
  228.         p->K_IN.kp_pb=(IOParam *)pb;
  229.         return soft_tnc_bytes_read(p,FALSE);
  230.     case sh_CONTROL:
  231.         if (csCode==1)
  232.             sfk_mark_read_done(p,-27);
  233.         else if (csCode==accRun)
  234.             soft_tnc_tick(p);
  235.         break;
  236.     default:
  237.         DBO_fprintf((&p->dbo,"soft_tnc op=%d csCode=%d\n",op,pb->csCode));
  238.         break;
  239.     }
  240.     return 0;
  241. }
  242.  
  243. /*
  244.  * fake driver for serial output in tnc mode
  245.  */
  246. static short soft_tnc_out(CntrlParam *pb,DCtlPtr de,short op,void *extra)
  247. {
  248.     register IOParam *ipb= (IOParam *)pb;
  249.     sfk_prt_pt p=extra;
  250.     switch(op) {
  251.     case sh_OPEN:
  252.         if(sfk_open_me(de))
  253.             return ioErr;
  254.         break;
  255.     case sh_CLOSE:
  256.         sfk_close_me(de);
  257.         break;
  258.     case sh_PRIME:
  259.         sfk_cu_write(&p->K_OUT.io_buf,ipb->ioBuffer,ipb->ioReqCount);
  260.         break;
  261.     default:
  262.         DBO_fprintf((&p->dbo,"soft_tnc_out csCode=%d\n",pb->csCode));
  263.         break;
  264.     }
  265.     return 0;
  266. }
  267.  
  268. /*
  269.  * allocate memory for soft_tnc
  270.  */
  271. void sfk_allocate_soft_tnc_memory(sfk_iio_pt cmd,sfk_prt_pt p)
  272. {
  273. #define IO_BUF_SIZE (5000)
  274.     if(p->K_IN.io_buf.cu_size==0)
  275.         sfk_cu_init(&p->K_IN.io_buf,IO_BUF_SIZE);
  276.     if(p->K_OUT.io_buf.cu_size==0)
  277.         sfk_cu_init(&p->K_OUT.io_buf,IO_BUF_SIZE);
  278.     if(p->cmd_buf_limit==0) {
  279.         p->cmd_port=p->pnum;
  280.         p->cmd_buf_limit=IO_BUF_SIZE;
  281.         p->cmd_buf_len=0;
  282.         p->cmd_buf=sfk_malloc(p->cmd_buf_limit);
  283.     }
  284.     if((p->K_IN.io_buf.cu_buf==0)||
  285.        (p->K_OUT.io_buf.cu_buf==0)||
  286.        (p->cmd_buf_limit==0))
  287.       sfk_parse_fail(cmd,TEXT_NUM(28),0);
  288. }
  289.  
  290. /*
  291.  * install soft_tnc as the current fake serial driver
  292.  */
  293. void sfk_soft_tnc_install(sfk_iio_pt cmd,sfk_prt_pt p)
  294. {
  295.     sfk_fake_serial_install(cmd,p,
  296.         &p->K_IN,(long)&soft_tnc_in,
  297.         &p->K_OUT,(long)&soft_tnc_out);
  298.     sfk_allocate_soft_tnc_memory(cmd,p);
  299. }
  300.  
  301. /*
  302.  * find the low memory variable with this ports configuration info
  303.  */
  304. static uint8 *find_port(sfk_prt_pt p)
  305. {
  306.     uint8 *port_config= (uint8 *)0x0290; /*assume port a*/
  307.     if(p->pnum!=1)        /*check PortAUse and PortBUse*/
  308.         port_config= (uint8 *)0x0291;    /*port b use byte*/
  309.       return port_config;
  310. }
  311.  
  312. /*
  313.  * mark the port as being free
  314.  */
  315. static void release_port(sfk_prt_pt p)
  316. {
  317.     volatile uint8 *port_config=find_port(p);
  318.     volatile uint8 *xSPConfig = (uint8 *)0x1FB;
  319.     if(p->pnum==0)
  320.         (*xSPConfig)= ((*xSPConfig)&0xf0)|2;
  321.     else
  322.         (*xSPConfig)=  ((*xSPConfig)&0x0f)|0x20;
  323.     (*port_config)= 0xFF;
  324. }
  325.  
  326. /*
  327.  * make sure the scc hardware isn't in use by appletalk or async
  328.  */
  329. static aquire_port(sfk_iio_pt cmd,sfk_prt_pt p)
  330. {
  331.     volatile uint8 *port_config=find_port(p);
  332.     volatile uint8 *xSPConfig = (uint8 *)0x1FB;
  333.     uint8 sp_byte=(*xSPConfig);
  334.     if(p->pnum!=0)
  335.         sp_byte>>=4;
  336.     if(!p->sfk_IVAR(force_port)) {
  337.       if((sp_byte&0x0F)!=2)
  338.         sfk_parse_fail(cmd,TEXT_NUM(32),0);
  339.       if((*port_config)!=0x0FF)
  340.         sfk_parse_fail(cmd,TEXT_NUM(33),0);
  341.     }
  342.     if(p->pnum==0)
  343.         (*xSPConfig)= ((*xSPConfig)&0xf0)|2;
  344.     else
  345.         (*xSPConfig)=  ((*xSPConfig)&0x0f)|0x20;
  346.     (*port_config)= (*xSPConfig);
  347. }
  348.  
  349. /*
  350.  * turn off all usage of passed port
  351.  */
  352. static void soft_tnc_off(sfk_iio_pt cmd,sfk_prt_pt p)
  353. {
  354.     fake_serial_off(p);
  355.     p->sfk_IVAR(soft_tnc)=FALSE;
  356.     release_port(p);
  357. }
  358.  
  359. /*
  360.  * turn on port in tnc emulation mode
  361.  */
  362. static void soft_tnc_on(sfk_iio_pt cmd,sfk_prt_pt p)
  363. {
  364.     aquire_port(cmd,p);
  365.     sfk_soft_tnc_install(cmd,p);
  366.     fake_serial_on(cmd,p);
  367.     STNC_put(p,SFK_TEXT(54));
  368.     STNC_put(p,__DATE__);
  369.     STNC_put(p,SFK_TEXT(55));
  370.     STNC_put(p,__TIME__);
  371.     STNC_put(p,SFK_TEXT(59));
  372.     STNC_put(p,SFK_TEXT(56));
  373.     STNC_put(p,sfk_gl.vers);
  374.     STNC_put(p,SFK_TEXT(59));
  375.     p->sfk_IVAR(soft_tnc)=TRUE;
  376. }
  377.  
  378. /*
  379.  * change tnc mode to on or off
  380.  */
  381. void sfk_change_soft_tnc(sfk_iio_pt cmd,int new_setting)
  382. {
  383.     if(cmd->pqx.p->sfk_IVAR(soft_tnc)==new_setting)
  384.         return;
  385.     if(cmd->pqx.p->pnum>1)
  386.       sfk_parse_fail(cmd,TEXT_NUM(39),0);
  387.     if(is_serial_busy(cmd->pqx.p))
  388.       sfk_parse_fail(cmd,TEXT_NUM(40),0);
  389.     if(new_setting)
  390.         soft_tnc_on(cmd,cmd->pqx.p);
  391.     else
  392.         soft_tnc_off(cmd,cmd->pqx.p);
  393. }
  394.  
  395.